#ifndef YEP_UI_WIDGET_HPP
#define YEP_UI_WIDGET_HPP

#include "../math/Rect.hpp"
#include "../math/Vector2.hpp"
#include "StyleBase.hpp"
#include "../framework/Entity.hpp"
#include "../framework/Event.hpp"

namespace yep
{
/**
 * @brief The base class for all widgets.
 **/
class Widget
{
public:
	/**
	 * @brief Constructor
	 **/
	Widget();

	/**
	 * @brief Destructor
	 **/
	virtual ~Widget();

	/**
	 * @brief Called when the Widget must be redrawn.
	 *
	 * Generally it is once per frame, but can vary for more or less.
	 **/
	virtual void onDraw(SDL_Surface *screen) =0;

	/**
	 * @brief Called every time the child area is changed.
	 *
	 * It is automatically called from the Area(Area &).
	 **/
	virtual void onChildSizeChange(Widget & child, const Rect & newArea);

	/**
	 * @brief Should handle events, specially mouse move, mouse button and keyboard.
	 *
	 * It should return false when the event is consumed (must not be passed to any other object.
	 **/
	virtual bool onEvent(SDL_Event & event);

	/**
	 * @brief Occurs when a mouse button is pressed inside the widget _area.
	 **/
	virtual bool onClickDown(SDL_MouseButtonEvent & buttonEvent);

	/**
	 * @brief Called every time a child gains or loses focus.
	 *
	 * It is automatically called on Focus(bool).
	 **/
	virtual void onChildFocusChange(Widget & child, bool gained);

	/**
	 * @brief Returns the area.
	 *
	 * It is only the logic area, relative to parent.
	 **/
	const Rect & getRect() const;

	/**
	 * @brief Changes the area.
	 *
	 * It is only the logic area, relative to parent. Every time this method is called
	 *  Its call parent->ChildAreaChange().
	 **/
	void setRect(const Rect & value);

	/**
	 * @brief Return the relative to parent position
	 **/
	Vector2 getPosition() const;

	/**
	 * @brief Changes the relative to parent position
	 **/
	void setPosition(const Vector2 & value);

	/**
	 * @brief Returns the absolute position.
	 *
	 * The position witch is actually drawn on screen.
	 **/
	const Vector2 & getAbsolutePosition() const;

	/**
	 * @brief Changes the absolute position.
	 *
	 * The position witch is actually drawn on screen. <b>Warning: This method should
	 *  be called only by the parent to its child. </b>
	 **/
	void setAbsolutePosition(const Vector2 & value);

	/**
	 * @brief Returns the absolute Area.
	 *
	 * The portion of widget witch is actually drawn on screen.
	 **/
	const Rect & getAbsoluteArea() const;

	/**
	 * @brief Changes the absolute Area.
	 *
	 * The portion of widget witch is actually drawn on screen. <b>Warning: This method should
	 *  be called only by the parent to its child. </b>
	 **/
	void setAbsoluteArea(const Rect & value);

	/**
	 * @brief Returns a pointer to parent or NULL.
	 **/
	Widget *getParent() const;

	/**
	 * @brief Sets the parent.
	 *
	 * <b>Warning: This method should
	 *  be called only by the parent to its child. </b>
	 **/
	void setParent(Widget *value);

	/**
	 * @brief Returns whether it is focused.
	 **/
	bool isFocused() const;

	/**
	 * @return changes the focus.
	 **/
	void setFocused(bool value);

	//        /**
	//         * @brief Returns the style.
	//         **/
	//        StyleBase& getStyle()
	//        {
	//            return *style;
	//        }
	//
	//        /**
	//         * @brief Changes the style.
	//         **/
	//        void setStyle( StyleBase& value )
	//        {
	//            style = &value;
	//        }
	/**
	 * @brief Return the left border.
	 **/
	Uint8 getLeftBorder() const;

	/**
	 * @brief Changes the left border
	 **/
	void setLeftBorder(Uint8 value);

	/**
	 * @brief Return the right border.
	 **/
	Uint8 getRightBorder() const;

	/**
	 * @brief Changes the right border
	 **/
	void setRightBorder(Uint8 value);

	/**
	 * @brief Return the top border.
	 **/
	Uint8 getTopBorder() const;

	/**
	 * @brief Changes the top border
	 **/
	void setTopBorder(Uint8 value);

	/**
	 * @brief Return the left border.
	 **/
	Uint8 getBottomBorder() const;

	/**
	 * @brief Changes the left border
	 **/
	void setBottomBorder(Uint8 value);

	/**
	 * @brief Returns the text color.
	 **/
	const Color & getTextColor() const;

	/**
	 * @brief Changes the textColor
	 **/
	void setTextColor(const Color & value);

	/**
	 * @brief Returns the text color.
	 **/
	const Color & getBackgroundColor() const;

	/**
	 * @brief Changes the textColor
	 **/
	void setBackgroundColor(const Color & value);
	//        /**
	//         * @brief Adjust the borders
	//         **/
	//        void autoAdjustBorders()
	//        {
	//            Uint8 left, top, right, bottom;
	//            style->windowBorders(left, top, right, bottom);
	//            setLeftBorder(left);
	//            setTopBorder(top);
	//            setRightBorder(right);
	//            setBottomBorder(bottom);
	//        }
private:
	Rect rect;
	Vector2 absolutePosition;
	Rect absoluteRect;
	Widget *parent;
	bool focused;
	Uint8 leftBorder, rightBorder, topBorder, bottomBorder;
	Color textColor, backgroundColor;
protected:
	StyleBaseOld *style;
};

}

#endif // YEP_UI_WIDGET_HPP
